import { CarouselComponent } from './carousel.component';
import { Component, OnInit, ElementRef, Input, Inject, forwardRef } from '@angular/core';
import { SafeStyle, DomSanitizer } from '@angular/platform-browser';
import { fadeAnimation } from '../shared/animation/index';
import { removeNgTag } from '../shared/utils/index';

@Component({
  selector: 'el-carousel-item',
  animations: [fadeAnimation],
  templateUrl: './carousel-item.component.html'
})
export class CarouselItemComponent implements OnInit {
  root: any;
  private sanitizer: any;
  private el: any;
  @Input() index: number = 0;
  @Input() label: string = '';
  width: number = 0;
  preTranslate: number = 0;
  isAnimating: boolean = false;
  isActive: boolean = false;
  styles!: SafeStyle;
  hover: boolean = false;
  inStage: boolean = false;
  scale: string | number = '';
  translate: string | number = '';
  CARD_SCALE: number = 0.83;

  constructor(@Inject(forwardRef(() => CarouselComponent)) root: CarouselComponent, sanitizer: DomSanitizer, el: ElementRef) {
    this.root = root;
    this.sanitizer = sanitizer;
    this.el = el;
  };

  calcCardTranslate(index: number, activeIndex: number) {
    const parentWidth = this.width;
    if (this.inStage) {
      return parentWidth * ((2 - this.CARD_SCALE) * (index - activeIndex) + 1) / 4;
    } else if (index < activeIndex) {
      return -(1 + this.CARD_SCALE) * parentWidth / 4;
    } else {
      return (3 + this.CARD_SCALE) * parentWidth / 4;
    }
  }

  calcTranslate(index: number, activeIndex: number, isVertical: boolean) {
    const distance = this.el.nativeElement.children[0][isVertical ? 'offsetHeight' : 'offsetWidth'];
    return distance * (index - activeIndex);
  }


  updateActive(): void {
    const isActive: boolean = this.root.model === this.index
    if (this.isActive !== isActive) {
      this.isActive = isActive
    }
  }


  updateStyles(len: number): void {
    const offset: number = this.root.model - this.index;
    const parentDirection = this.root.direction;
    const parentType = this.root.type;
    var translate: number = 0;
    var scale: number = 1;
    if (parentType === 'card') {
      if (parentDirection === 'vertical') {
        console.warn('[Element Warn][Carousel]vertical direction is not supported in card mode');
      }
      var index = this.index;
      if (index !== this.root.model && len > 2) {
        index = this.processIndex(this.index,this.root.model,len);
      }
      
      this.inStage = Math.round(Math.abs(index - this.root.model)) <= 1;
// console.log(index, this.inStage,this.index);
      translate = this.calcCardTranslate(index, this.root.model);
      scale = this.isActive ? 1 : this.CARD_SCALE;
    } else {
      const isVertical = parentDirection === 'vertical';
      translate = this.calcTranslate(this.index, this.root.model, isVertical);
    }

    const translateType = parentDirection === 'vertical' ? 'translateY' : 'translateX';
    const styles: string = `transform: ${translateType}(${translate}px) scale(${scale});`
    // change direction disable animation
    const changeDirection: boolean = (this.preTranslate < 0 && translate > 0)
      || (this.preTranslate > 0 && translate < 0)
    this.isAnimating = !changeDirection
    this.styles = this.sanitizer.bypassSecurityTrustStyle(styles)
    // console.log(this.styles);
    // save current value
    this.preTranslate = translate
  }


  processIndex(index: number, activeIndex: number, length: number) {
    if (activeIndex === 0 && index === length - 1) {
      return -1;
    } else if (activeIndex === length - 1 && index === 0) {
      return length;
    } else if (index < activeIndex - 1 && activeIndex - index >= length / 2) {
      return length + 1;
    } else if (index > activeIndex + 1 && index - activeIndex >= length / 2) {
      return -2;
    }
    return index;
  }

  update(): void {
    this.updateStyles(0)
    this.updateActive()
  }

  ngOnInit(): void {
    // collect items
    this.root.items.push(this.label)
    this.width = this.el.nativeElement.children[0].offsetWidth
    removeNgTag(this.el.nativeElement)

    // manually update
    this.root.subscriber.push(() => this.update())
    this.update()
  }

}
